/*
 * Copyright 2007 - The JDPF Project Team (http://www.jdpf.org) 
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License. 
 * You may obtain a copy of the License at 
 * 
 * http://www.apache.org/licenses/LICENSE-2.0 
 * 
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS, 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and 
 * limitations under the License. 
 */
package org.jdpf.plugins.measureseries.serializer.file.delimitedfilewriter;

import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.List;

import org.jdpf.core.kernel.elements.Token;
import org.jdpf.core.plugins.blocks.AbstractSerializerPlugin;
import org.jdpf.core.plugins.datatypes.AbstractDataType;
import org.jdpf.core.plugins.exceptions.PluginException;
import org.jdpf.core.plugins.exceptions.PluginExceptionsEnum;
import org.jdpf.plugins.datatypes.basic.MeasureAdapter;
import org.jdpf.plugins.datatypes.basic.MeasureSeries;
import org.jdpf.plugins.datatypes.temporal.TimestampedMeasureAdapter;

/**
 * This plugin is a serializer that writes integer values to a file.
 * 
 * @author Cristiana Larizza
 * @author Paolo Ciccarese
 */

public class MeasureSeriesDelimitedFileWriter extends AbstractSerializerPlugin {
    
	// Plugin parameters
    // -----------------
    private String _lineFormat = "dt";		// Optional
	private String _outputFile; 			// Location of the file to be read
    private String _tokensSeparator = Character.toString('\t');
    private String _timestampFormat = "yyyy-MM-dd HH:mm:ss"; // The timestamp related to a particular value
	
    public void setOutputFile(String fileName) {
		_outputFile = fileName;
	}

	public void setLineFormat(String lineFormat) {
		_lineFormat = lineFormat;
	}	

	public void setTokensSeparator(String separator) {
		if (separator.equalsIgnoreCase("tab"))
				separator = Character.toString('\t');
		else if (separator.equalsIgnoreCase("newline"))
				separator = Character.toString('\n');
		else if (separator.equalsIgnoreCase("space") || separator.equals(""))
			separator = Character.toString(' ');
		_tokensSeparator = separator;
	}	

	public void setTimestampFormat(String timestamp_format) {
		if (timestamp_format != null) _timestampFormat = timestamp_format;
	}

 	/**
	 * Constructor for a Generator Plugin.
     * @param transitionId The id of the transition related to this plugin
     * @param transitionName The name of the transition related to this plugin
     */
    public MeasureSeriesDelimitedFileWriter(String transitionId, String transitionName) {
		super(transitionId, transitionName);
	}
    
    @SuppressWarnings("unchecked")
	public Token process(List<Token> list) throws PluginException{
    	
		for(AbstractDataType adt:list.get(0).getValueList()){
			writeFileFromSeries(_outputFile, (MeasureSeries) adt);
		} 			
    	return new Token();
    }

    private void writeFileFromSeries(String fileName, MeasureSeries valueList) throws PluginException {
 
    	// Elements' position detection
    	int dataPosition = _lineFormat.indexOf('d');
    	int timePosition = _lineFormat.indexOf('t');
    	int unitPosition = _lineFormat.indexOf('u');
    	
    	String[] tokens = new String[3];
    	
    	SimpleDateFormat sdf = new SimpleDateFormat(_timestampFormat);

    	try {
    		PrintWriter pr = new PrintWriter(new FileWriter(fileName));
    		
    		this.logMainPoint(this, this.getPluginId(), this.getId(), "Writing started.");
    		
    		int length = valueList.getSize(), i = 0;
    		for(AbstractDataType value: valueList.getValue()) {
    			if(!start) break;
    			i++;
    			percentage = ((double)i / length) * 100;
    			
    			initializeTokens(tokens);
    			tokens[dataPosition] = value.getStringValue();
     	    	if(timePosition>-1)
    	    		tokens[timePosition] = sdf.format(((TimestampedMeasureAdapter)value).getTimestamp());
    	    	if(unitPosition>-1)
    	    		tokens[unitPosition] = ((MeasureAdapter)value).getMeasure().getUnit().toString();

    			if (value instanceof TimestampedMeasureAdapter)  {
    				pr.println(tokens[0] 
    				        + (tokens[1]!=null && !tokens[1].equals("")? _tokensSeparator:"") + tokens[1]
    				        + (tokens[2]!=null && !tokens[2].equals("")? _tokensSeparator:"") + tokens[2]);
    				this.log(this, this.getPluginId(), this.getId(), "Out: " + tokens[0] 
    				    + (tokens[1]!=null && !tokens[1].equals("")? _tokensSeparator:"") + tokens[1]
    				    + (tokens[2]!=null && !tokens[2].equals("")? _tokensSeparator:"") + tokens[2]);
    			} else {
        			pr.println(tokens[dataPosition] + ((unitPosition!=-1? (_tokensSeparator+ tokens[unitPosition]):"") ));
    				this.log(tokens[dataPosition] + ((unitPosition!=-1? (_tokensSeparator+ tokens[unitPosition]):"") ));
    			}
    		}
    		this.logMainPoint(this, this.getPluginId(), this.getId(), "Writing completed!");
    		pr.close();
    	} catch (IOException e) {
    		this.error(this, this.getPluginId(), this.getId(), "The output file " + _outputFile + " cannot be created: "
    				+ e.getMessage());
    		throw new PluginException(PluginExceptionsEnum.ExecutionError, this.getPluginId(), 
    				"The output file " + _outputFile + " cannot be created: "
    				+ e.getMessage());
    	}
    }
			
    private void initializeTokens(String[] tokens){
    	for (int i=0; i<tokens.length; i++)
    		tokens[i] = "";
    }
}
